﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Client
{
    [StructLayout(LayoutKind.Sequential)]
    struct AdditionResult
    {
        public uint result;
        public uint errorCode;

        public static implicit operator Tuple<uint, uint>(AdditionResult result)
        {
            return Tuple.Create(result.result, result.errorCode);
        }

        public static implicit operator AdditionResult(Tuple<uint, uint> result)
        {
            return new AdditionResult { result = result.Item1, errorCode = result.Item2 };
        }
    };

    class Program
    {
        [DllImport("api", EntryPoint = "addition")]
        private static extern AdditionResult Addition(uint a, uint b);

        static void TestApi()
        {
            void AssertAddition(uint a, uint b, (uint, uint) expectedResult)
            {
                var result = Addition(a, b);

                Debug.Assert(expectedResult.Item1 == result.result);
                Debug.Assert(expectedResult.Item2 == result.errorCode);
            }

            AssertAddition(0, 0, (0, 0));
            AssertAddition(0, 1, (1, 0));
            AssertAddition(0, uint.MaxValue, (uint.MaxValue, 0));
            AssertAddition(1, 0, (1, 0));
            AssertAddition(1, 1, (2, 0));
            AssertAddition(1, uint.MaxValue - 1, (uint.MaxValue, 0));
            AssertAddition(1, uint.MaxValue, (0, 1));
        }

        static void Main(string[] args)
        {
            var result = Addition(1, 2);
            Console.WriteLine($"result: {result.result}, errorCode: {result.errorCode}");

            TestApi();
        }
    }
}
